import {
  HttpException,
  HttpStatus,
  Inject,
  Injectable,
  Logger,
} from '@nestjs/common';
import { RegisterUserDto } from './dto/register-user.dto';
import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm';
import { Like, Repository } from 'typeorm';
import { User } from './entities/user.entity';
import { RedisService } from 'src/redis/redis.service';
import { md5 } from 'src/utils';
import { Role } from './entities/role.entity';
import { Permission } from './entities/permission.entity';
import { LoginUserDto } from './dto/login-user.dto';
import { LoginUserVO } from './vo/login-user.vo';
import { UserDetailVo } from './vo/user-info.vo';
import { UpdatePasswordUserDto } from './dto/update-password-user-dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { UserListDto } from './dto/user-list.dto';

@Injectable()
export class UserService {
  private logger = new Logger();
  @InjectRepository(User)
  private userRepository: Repository<User>;
  @InjectRepository(Role)
  private roleRepository: Repository<Role>;
  @InjectRepository(Permission)
  private permissionRepository: Repository<Permission>;
  @Inject()
  private redisServeice: RedisService;
  async register(user: RegisterUserDto) {
    const captcha = await this.redisServeice.get(`captcha_${user.email}`);
    if (!captcha) {
      throw new HttpException('验证码已过期', HttpStatus.BAD_REQUEST);
    }
    if (user.captcha !== captcha) {
      throw new HttpException('验证码错误', HttpStatus.BAD_REQUEST);
    }
    const foundUser = await this.userRepository.findOneBy({
      username: user.username,
    });
    if (foundUser) {
      throw new HttpException('该用户名已存在', HttpStatus.BAD_REQUEST);
    }
    const newUser = new User();
    newUser.username = user.username;
    newUser.password = md5(user.password);
    newUser.email = user.email;
    newUser.nickName = user.nickName;
    try {
      await this.userRepository.save(newUser);
      return { message: '注册成功' };
    } catch (e) {
      this.logger.error(e, UserService);

      throw new HttpException('注册失败', HttpStatus.BAD_REQUEST);
    }
  }
  async initData() {
    const user1 = new User();
    user1.username = 'zhangsan';
    user1.password = md5('111111');
    user1.email = 'xxx@xx.com';
    user1.isAdmin = true;
    user1.nickName = '张三';
    user1.phoneNumber = '13233323333';

    const user2 = new User();
    user2.username = 'lisi';
    user2.password = md5('222222');
    user2.email = 'yy@yy.com';
    user2.nickName = '李四';

    const role1 = new Role();
    role1.name = '管理员';

    const role2 = new Role();
    role2.name = '普通用户';

    const permission1 = new Permission();
    permission1.code = 'ccc';
    permission1.description = '访问 ccc 接口';

    const permission2 = new Permission();
    permission2.code = 'ddd';
    permission2.description = '访问 ddd 接口';

    user1.roles = [role1];
    user2.roles = [role2];

    role1.permissions = [permission1, permission2];
    role2.permissions = [permission1];

    await this.permissionRepository.save([permission1, permission2]);
    await this.roleRepository.save([role1, role2]);
    await this.userRepository.save([user1, user2]);
  }
  async userLogin(user: LoginUserDto, isAdmin: boolean) {
    const { username, password } = user;
    const foundUser = await this.userRepository.findOne({
      where: {
        username: username,
        isAdmin,
      },
      relations: ['roles', 'roles.permissions'],
    });
    if (!foundUser) {
      throw new HttpException('该用户不存在', HttpStatus.BAD_REQUEST);
    }
    if (foundUser.password !== md5(password)) {
      throw new HttpException('密码错误', HttpStatus.BAD_REQUEST);
    }

    const vo = new LoginUserVO();
    vo.userInfo = {
      id: foundUser.id,
      username: foundUser.username,
      nickName: foundUser.nickName,
      email: foundUser.email,
      phoneNumber: foundUser.phoneNumber,
      headPic: foundUser.headPic,
      createTime: foundUser.createTime,
      // isFrozen:foundUser.isFrozen,
      isAdmin: foundUser.isAdmin,
      roles: foundUser.roles.map((item) => item.name),
      permissions: foundUser.roles.reduce((arr, item) => {
        item.permissions.forEach((permission) => {
          if (arr.indexOf(permission) === -1) {
            arr.push(permission);
          }
        });
        return arr;
      }, []),
    };
    return vo;
  }
  async findUserById(userId: number, isAdmin: boolean) {
    const user = await this.userRepository.findOne({
      where: {
        id: userId,
        isAdmin,
      },
      relations: ['roles', 'roles.permissions'],
    });
    return {
      id: user.id,
      username: user.username,
      isAdmin: user.isAdmin,
      roles: user.roles.map((item) => item.name),
      permissions: user.roles.reduce((arr, item) => {
        item.permissions.forEach((permission) => {
          if (arr.indexOf(permission) === -1) {
            arr.push(permission);
          }
        });
        return arr;
      }, []),
    };
  }
  async findUserDetailById(userId: number) {
    const user = await this.userRepository.findOne({
      where: {
        id: userId,
      },
      relations: ['roles', 'roles.permissions'],
    });
    if (!user) {
      throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
    }

    const vo = new UserDetailVo();
    vo.id = user.id;
    vo.email = user.email;
    vo.username = user.username;
    vo.headPic = user.headPic;
    vo.phoneNumber = user.phoneNumber;
    vo.nickName = user.nickName;
    vo.createTime = user.createTime;
    return vo;
  }
  async updatePassword(passwordDto: UpdatePasswordUserDto) {
    const { username } = passwordDto;
    const user = await this.userRepository.findOne({
      where: {
        username: username,
      },
    });
    if (!user) {
      throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
    }
    if (user.email !== passwordDto.email) {
      throw new HttpException('邮箱错误', HttpStatus.BAD_REQUEST);
    }
    user.password = md5(passwordDto.password);
    try {
      await this.userRepository.update(username, user);
      return '密码修改成功';
    } catch (e) {
      this.logger.error(e, UserService);

      throw new HttpException('密码修改失败', HttpStatus.BAD_REQUEST);
    }
  }
  async updateUser(userId: number, updateUserDto: UpdateUserDto) {
    const user = await this.userRepository.findOne({
      where: {
        id: userId,
      },
    });
    if (updateUserDto.nickName) {
      user.nickName = updateUserDto.nickName;
    }
    if (updateUserDto.headPic) {
      user.headPic = updateUserDto.headPic;
    }
    if (updateUserDto.email) {
      user.email = updateUserDto.email;
    }
    try {
      await this.userRepository.update(userId, user);
      return '修改成功';
    } catch (e) {
      this.logger.error(e, UserService);
      throw new HttpException('修改失败', HttpStatus.BAD_REQUEST);
    }
  }
  async userList(userListDto: UserListDto) {
    const skipCount = (userListDto.pageNo - 1) * userListDto.pageSize;
    const condition: Record<string, any> = {};
    if (userListDto.username) {
      condition.username = Like(`%${userListDto.username}%`);
    }
    if (userListDto.nickName) {
      condition.nickName = Like(`%${userListDto.nickName}%`);
    }
    if (userListDto.phoneNumber) {
      condition.phoneNumber = userListDto.phoneNumber;
    }

    const [users, totalCount] = await this.userRepository.findAndCount({
      skip: skipCount,
      take: userListDto.pageSize,
      select: [
        'id',
        'username',
        'nickName',
        'phoneNumber',
        'createTime',
        'email',
        'headPic',
      ],
      where: condition,
    });
    return {
      users,
      totalCount,
    };
  }
}
